using System;
using System.IO;
using System.Text;
using System.Threading;

namespace ProgramLauncher.Utils
{
    public static class Logger
    {
        private const string LOG_FOLDER = "logs";
        private const string LOG_FILE = "app.log";
        private static readonly string LogPath;
        private static readonly object LogLock = new object();
        private static readonly int MAX_LOG_SIZE = 10 * 1024 * 1024; // 10MB
        private static readonly Encoding LogEncoding = Encoding.UTF8;
        private static bool _isInitialized;

        static Logger()
        {
            try
            {
                LogPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, LOG_FOLDER, LOG_FILE);
                EnsureLogDirectory();
            }
            catch (Exception ex)
            {
                // 在静态构造函数中发生异常是致命的，记录到Windows事件日志
                System.Diagnostics.EventLog.WriteEntry("ProgramLauncher", 
                    $"日志系统初始化失败: {ex.Message}", 
                    System.Diagnostics.EventLogEntryType.Error);
                throw;
            }
        }

        private static void EnsureLogDirectory()
        {
            var logDir = Path.GetDirectoryName(LogPath);
            if (!Directory.Exists(logDir))
            {
                Directory.CreateDirectory(logDir);
            }
        }

        public static void Initialize()
        {
            if (_isInitialized) return;

            try
            {
                lock (LogLock)
                {
                    if (_isInitialized) return;

                    // 检查日志文件大小，如果超过限制则备份
                    if (File.Exists(LogPath))
                    {
                        var fileInfo = new FileInfo(LogPath);
                        if (fileInfo.Length > MAX_LOG_SIZE)
                        {
                            string backupPath = Path.Combine(
                                Path.GetDirectoryName(LogPath),
                                $"app_{DateTime.Now:yyyyMMdd_HHmmss}.log"
                            );
                            File.Move(LogPath, backupPath);
                        }
                    }

                    LogInfo("=== 程序启动 ===");
                    _isInitialized = true;
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.EventLog.WriteEntry("ProgramLauncher",
                    $"日志系统初始化失败: {ex.Message}",
                    System.Diagnostics.EventLogEntryType.Error);
                throw;
            }
        }

        public static void LogInfo(string message)
        {
            WriteLog("INFO", message);
        }

        public static void LogError(string message, Exception ex = null)
        {
            StringBuilder sb = new StringBuilder();
            sb.AppendLine(message);

            if (ex != null)
            {
                sb.AppendLine($"异常类型: {ex.GetType().FullName}");
                sb.AppendLine($"异常信息: {ex.Message}");
                sb.AppendLine($"堆栈跟踪: {ex.StackTrace}");

                // 记录内部异常
                var innerException = ex.InnerException;
                while (innerException != null)
                {
                    sb.AppendLine($"内部异常: {innerException.GetType().FullName}");
                    sb.AppendLine($"内部异常信息: {innerException.Message}");
                    sb.AppendLine($"内部异常堆栈: {innerException.StackTrace}");
                    innerException = innerException.InnerException;
                }
            }

            WriteLog("ERROR", sb.ToString());
        }

        private static void WriteLog(string level, string message)
        {
            if (string.IsNullOrEmpty(message)) return;

            try
            {
                string logMessage = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{Thread.CurrentThread.ManagedThreadId}] [{level}] {message}{Environment.NewLine}";

                // 使用文件锁确保线程安全
                lock (LogLock)
                {
                    int retryCount = 3;
                    while (retryCount > 0)
                    {
                        try
                        {
                            // 使用 using 语句确保资源正确释放
                            using (var writer = new StreamWriter(LogPath, true, LogEncoding))
                            {
                                writer.Write(logMessage);
                                writer.Flush();
                                break;
                            }
                        }
                        catch (IOException) when (retryCount > 1)
                        {
                            // 如果是IO异常且还有重试次数，则等待后重试
                            Thread.Sleep(100);
                            retryCount--;
                        }
                        catch
                        {
                            // 其他异常或重试次数用完，直接抛出
                            throw;
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                // 日志写入失败时，尝试写入Windows事件日志
                try
                {
                    System.Diagnostics.EventLog.WriteEntry("ProgramLauncher",
                        $"写入日志失败: {ex.Message}\n原始日志: [{level}] {message}",
                        System.Diagnostics.EventLogEntryType.Error);
                }
                catch
                {
                    // 如果连Windows事件日志都写不了，那就真的没办法了
                    // 在这种情况下，我们不能抛出异常，因为这可能会导致应用程序崩溃
                }
            }
        }

        public static void Shutdown()
        {
            try
            {
                LogInfo("=== 程序关闭 ===");
            }
            catch
            {
                // 关闭时的日志错误可以忽略
            }
        }
    }
} 